#include <croco/os/pipe.hpp>
#include <croco/common_exceptions.hpp>
#include <unistd.h>
#include <cerrno>
#include <cassert>

namespace cros = croco::os;

cros::pipe::pipe()
: m_r(0), m_w(0)
{
    native_handle_type fd[2] = { 0, 0 };
    int status = ::pipe(fd);
    if(status != 0)
    {
        throw os_error() << boost::errinfo_api_function("pipe") << boost::errinfo_errno(errno) << more_info("pipe creation failed");
    }
    m_r = fd[0];
    m_w = fd[1];
}

int cros::pipe::write(const char* data, std::size_t size) const
{
    assert(data);
    int written = ::write(m_w, data, size);
    if(written == -1)
    {
        throw os_error() << boost::errinfo_api_function("write") << boost::errinfo_errno(errno) << more_info("writing to pipe failed");
    }
    return written;
}

int cros::pipe::read(char* buffer, std::size_t size) const
{
    assert(buffer);
    int read = ::read(m_r, buffer, size);
    if(read == -1)
    {
        throw os_error() << boost::errinfo_api_function("read") << boost::errinfo_errno(errno) << more_info("reading from pipe failed");
    }
    return read;
}
